package org.leon.service;

import org.apache.commons.lang3.RandomUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.leon.dao.AuthCodeRepository;
import org.leon.entity.AuthCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;

@Service
public class AuthCodeServiceImpl implements AuthCodeService {

    private AuthCodeRepository authCodeRepository;

    @Reference
    private EmailService emailService;

    @Autowired
    public AuthCodeServiceImpl(AuthCodeRepository authCodeRepository) {
        this.authCodeRepository = authCodeRepository;
    }

    @Override
    public Boolean createAndSendCode(String email) {
        // 1. 生成6位数字验证码
        int randomVal = RandomUtils.nextInt(100000, 999999);
        String code = randomVal + "";

        // 2. 验证码入库
        insertCodeRecord(email, code);

        // 3. 调用验证码发送微服务
        Boolean ret = true;
        try {
            emailService.sendMail(email, code);
        } catch (Exception e) {
            e.printStackTrace();
            ret = false;
        }

        return ret;
    }

    /**
     * 验证指定邮箱的验证码: 0-正确 1-错误 2-超时
     */
    @Override
    public Integer checkCode(String email, String code) {
        // 1 根据 email 从数据库中找到最新的一条验证码记录
        AuthCode authCode = findByEmail(email, code);

        // 2 判断是否正确
        if (authCode == null || !authCode.getCode().equals(code)) {
            return 1;
        }

        // 3 判断是否超时
        if ( authCode.getExpireTime().before(new Date()) ) {
            return 2;
        }
        return 0;
    }

    /**
     * 操作数据库, 插入一条认证码记录
     */
    private void insertCodeRecord(String email, String code) {

        LocalDateTime now = LocalDateTime.now();
        Date createTime = Date.from( now.atZone(ZoneId.systemDefault()).toInstant() );
        LocalDateTime nowAfterPlus = LocalDateTime.now().plus(10, ChronoUnit.MINUTES);
        Date expireTime = Date.from( nowAfterPlus.atZone(ZoneId.systemDefault()).toInstant() );


        AuthCode authCode = new AuthCode();
        authCode.setCode(code);
        authCode.setEmail(email);
        authCode.setCreateTime(createTime);
        authCode.setExpireTime(expireTime);


        authCodeRepository.save(authCode);
    }

    /**
     * 根据指定邮箱返回最新的一条记录
     */
    private AuthCode findByEmail(String email, String code) {

        AuthCode authCode = new AuthCode();
        authCode.setEmail(email);
        authCode.setCode(code);
        Example example = Example.of(authCode);

        PageRequest pageRequest = PageRequest.of(0, 1, new Sort(Sort.Direction.DESC, "id"));

        Page<AuthCode> results = authCodeRepository.findAll(example, pageRequest);
        if (results.hasContent()){
            return results.getContent().get(0);
        }
        return null;
    }
}
